/*
 * Copyright 2025 The JA-SIG Collaborative. All rights reserved.
 * distributed with this file and available online at
 */
package com.lap.auth.application.organization.assembler;

import com.lap.auth.application.organization.command.CreateOrgCmd;
import com.lap.auth.application.organization.command.UpdateOrgCmd;
import com.lap.auth.application.organization.dto.OrgNodeDto;
import com.lap.auth.application.organization.dto.OrgOptionDto;
import com.lap.auth.domain.organization.Organization;
import com.lap.auth.domain.organization.valueobject.Status;
import com.lap.auth.shared.tools.BaseConverter;
import com.lap.framework.common.tool.EnumUtil;
import java.util.*;
import org.apache.commons.lang3.StringUtils;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper(componentModel = "spring")
public interface OrgAssembler extends BaseConverter {

  Integer ZERO = 0;

  default Organization create(String code, CreateOrgCmd cmd) {
    String generateCode = (StringUtils.isBlank(cmd.getCode())) ? code : cmd.getCode();
    return new Organization(
        null,
        listToLastInt(cmd.getPidPaths()),
        listToStr(cmd.getPidPaths()),
        generateCode,
        cmd.getName(),
        codeToStatus(cmd.getStatus()),
        cmd.getRemark(),
        cmd.getSortOrder());
  }

  default Organization update(Integer id, String code, UpdateOrgCmd cmd) {
    return new Organization(
        id,
        listToLastInt(cmd.getPidPaths()),
        listToStr(cmd.getPidPaths()),
        code,
        cmd.getName(),
        codeToStatus(cmd.getStatus()),
        cmd.getRemark(),
        cmd.getSortOrder());
  }

  @Mapping(target = "pidPaths", source = "pidPath")
  @Mapping(target = "children", ignore = true)
  OrgNodeDto toDto(Organization organization);

  List<OrgNodeDto> toDtoList(List<Organization> list);

  OrgOptionDto toOptionDto(Organization organization);

  List<OrgOptionDto> toOptionDtoList(List<Organization> list);

  default Status codeToStatus(Integer code) {
    return EnumUtil.fromCode(Status.class, code);
  }

  default Integer statusToCode(Status status) {
    return status.getCode();
  }

  default List<OrgNodeDto> convertToTree(List<OrgNodeDto> allList) {
    List<OrgNodeDto> roots = new ArrayList<>();
    Map<Integer, OrgNodeDto> nodeMap = new HashMap<>();
    for (OrgNodeDto dto : allList) {
      dto.setChildren(new ArrayList<>());
      nodeMap.put(dto.getId(), dto);
    }

    for (OrgNodeDto dto : allList) {
      if (Objects.equals(dto.getParentId(), ZERO)) {
        roots.add(dto);
      } else {
        OrgNodeDto parent = nodeMap.get(dto.getParentId());
        if (parent != null) {
          parent.getChildren().add(dto);
        }
      }
    }

    for (OrgNodeDto dto : nodeMap.values()) {
      dto.getChildren().sort(Comparator.comparing(OrgNodeDto::getSortOrder));
    }
    roots.sort(Comparator.comparing(OrgNodeDto::getSortOrder));
    return roots;
  }
}
